/*INCLUDES-------------------------------------------------------------------*/

#include <string.h>

#include "ses_display_print.h"
#include "ses_display.h"
#include "ses_framebuffer.h"
#include "fonts/font6x8.h"

/*MACROS---------------------------------------------------------------------*/

#define CHARACTER_WIDTH  6
#define CHARACTER_HEIGHT 8

#define CURSOR_COLUMN_MAX 20
#define CURSOR_ROW_MAX 4

/*VARIABLES------------------------------------------------------------------*/

static FILE file;

/* Curserposition */
static uint8_t cursor_r;
static uint8_t cursor_c;

/*FUNCTION DEFINITION--------------------------------------------------------*/

/**
 * Wrapper for writing characters to the LCD. Function signature allows
 * usage in a file descriptor.
 *
 * @param chr		character to write
 * @param stream	passed stream instance
 */
static int put(char chr, FILE *stream) {
	displayPrint_put(chr);
	return 0;
}

void displayPrint_init() {
	display_init();
	display_clear();

	/* Set Cursor to start */
	cursor_c = cursor_r = 0;

	// DO NOT DELETE THESE LINES
	// - OK, I WILL NOT DELETE THESE LINES! ROGER!

	// initialize file descriptor in order to allow access display via fprintf
	memset(&file, 0, sizeof(FILE));
	file.put = put;
	file.get = NULL;
	file.flags = _FDEV_SETUP_WRITE;
	file.udata = 0;
	stdout = &file;

	// - HAVEN'T DELTED THESE LINES, OK?
}

/* Sets the internal cursorposition */
void displayPrint_setCursor(uint8_t p, uint8_t r) {
	/* Check if cursorposition is in range */
	if (p > CURSOR_COLUMN_MAX)
		return;
	if (r > CURSOR_ROW_MAX)
		return;

	cursor_r = r;
	cursor_c = p;
}

static void putCharToFramebuffer(char chr) {
	uint8_t i, t;

	/* For the Character width ... */
	for (i = 0; i < CHARACTER_WIDTH; i++) {
		/* ... and the height ... */
		for (t = 0; t < CHARACTER_HEIGHT; t++) {

			/* ... if the pixel in the font is black ... */
			if (font6x8[chr * 6 + i] & (1 << t)) {

				/* ... draw it ... */
				ses_setpixel(cursor_c * CHARACTER_WIDTH + i, cursor_r
						* CHARACTER_HEIGHT + t);
			} else {
				/* ... otherwise clear it. */
				ses_clrpixel(cursor_c * CHARACTER_WIDTH + i, cursor_r
						* CHARACTER_HEIGHT + t);
			}
		}
	}

	// Comprende ?
}

/* Puts a character on display */
void displayPrint_put(char chr) {
	/* If cursor position is out of range -> return */
	if(cursor_r >= CURSOR_ROW_MAX)return;

	/* If character is linefeed increase rowcursor ... */
	if(chr == '\n'){
		cursor_r++;
		cursor_c = 0;
	} else {
		/* ... else put character on screen */
		putCharToFramebuffer(chr);
		cursor_c++;
	}

	/* Wrap around the right edge */
	if (cursor_c >= CURSOR_COLUMN_MAX) {
		cursor_c = 0;
		cursor_r++;
	}

	/* Flush Framebuffer to Display */
	ses_framebuffer_flush();
}

